// --------------------------------------------------------------------------------------------------------------------
// <copyright file="App.xaml.cs" company="http://buginbox.wordpress.com/">
//   Copyright (c) GNU General Public License version 2 (GPLv2)
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Primitives;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Practices.Prism;
using Microsoft.Practices.Prism.Modularity;
using System.Linq;

namespace WpfPrismWithSplash
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="App"/> class.
        /// </summary>
        /// <exception cref="T:System.InvalidOperationException">More than one instance of the <see cref="T:System.Windows.Application"/> class is created per <see cref="T:System.AppDomain"/>.</exception>
        public App()
        {
            DispatcherUnhandledException += Application_DispatcherUnhandledException;
        }

        /// <summary>
        /// The on startup.
        /// </summary>
        /// <param name="e">
        /// The e. 
        /// </param>
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            var bootstrapper = new Bootstrapper();

            try
            {
                bootstrapper.Run();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }            
        }

        /// <summary>
        /// Traces the exception.
        /// </summary>
        /// <param name="exception">The exception.</param>
        private static void TraceException(Exception exception)
        {
            System.Diagnostics.Debug.WriteLine(exception.GetType().Name + " : " + exception.Message);
        }

        /// <summary>
        /// The application_ dispatcher unhandled exception.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            
            var exception = e.Exception;
            TraceException(exception);

            Shutdown(-1);
        }

        /// <summary>
        /// Handles the exception.
        /// </summary>
        /// <param name="exception">The exception.</param>
        private static void HandleException(Exception exception)
        {
            if (exception == null)
            {
                return;
            }

            if (exception is CompositionException)
            {
                exception = GetRootException(exception as CompositionException);
            }

            throw exception;
        }

        /// <summary>
        /// Gets the root exception.
        /// </summary>
        /// <param name="compositionException">The composition exception.</param>
        /// <returns></returns>
        private static Exception GetRootException(CompositionException compositionException)
        {
            var rootCause = compositionException.GetType().GetProperty("RootCauses").GetValue(compositionException, null) as ReadOnlyCollection<Exception>;

            if (rootCause == null)
            {
                return compositionException;
            }

            var current = rootCause.FirstOrDefault();

            while (current != null)
            {
                if (!(current is ComposablePartException)
                    && !(current is ModuleInitializeException))
                {
                    return current;
                }

                current = current.InnerException;
            }

            return compositionException;
        }
    }
}